home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / tcpdump-3.0.2 / print-atalk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-21  |  13.7 KB  |  572 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * Format and print AppleTalk packets.
  22.  */
  23. #ifndef lint
  24. static  char rcsid[] =
  25.     "@(#)$Header: print-atalk.c,v 1.36 94/06/20 19:44:34 leres Exp $ (LBL)";
  26. #endif
  27.  
  28. #include <sys/param.h>
  29. #include <sys/time.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32.  
  33. #include <net/if.h>
  34.  
  35. #include <netinet/in.h>
  36. #include <netinet/in_systm.h>
  37. #include <netinet/ip.h>
  38. #include <netinet/ip_var.h>
  39. #include <netinet/if_ether.h>
  40. #include <netinet/udp.h>
  41. #include <netinet/udp_var.h>
  42. #include <netinet/tcp.h>
  43. #include <netinet/tcpip.h>
  44.  
  45. #include <stdio.h>
  46. #ifdef __STDC__
  47. #include <stdlib.h>
  48. #endif
  49. #include <string.h>
  50.  
  51. #include "interface.h"
  52. #include "addrtoname.h"
  53. #include "ethertype.h"
  54. #include "extract.h"            /* must come after interface.h */
  55. #include "appletalk.h"
  56.  
  57. static struct token type2str[] = {
  58.     { ddpRTMP,        "rtmp" },
  59.     { ddpRTMPrequest,    "rtmpReq" },
  60.     { ddpECHO,        "echo" },
  61.     { ddpIP,        "IP" },
  62.     { ddpARP,        "ARP" },
  63.     { ddpKLAP,        "KLAP" },
  64.     { 0,            NULL }
  65. };
  66.  
  67. struct aarp {
  68.     u_short htype, ptype;
  69.     u_char    halen, palen;
  70.     u_short op;
  71.     u_char    hsaddr[6];
  72.     u_char    psaddr[4];
  73.     u_char    hdaddr[6];
  74.     u_char    pdaddr[4];
  75. };
  76.  
  77. static char tstr[] = "[|atalk]";
  78.  
  79. static void atp_print(const struct atATP *, int);
  80. static void atp_bitmap_print(u_char);
  81. static void nbp_print(const struct atNBP *, int, u_short, u_char, u_char);
  82. static const char *print_cstring(const char *, const u_char *);
  83. static const struct atNBPtuple *nbp_tuple_print(const struct atNBPtuple *,
  84.                         const u_char *,
  85.                         u_short, u_char, u_char);
  86. static const struct atNBPtuple *nbp_name_print(const struct atNBPtuple *,
  87.                            const u_char *);
  88. static const char *ataddr_string(u_short, u_char);
  89. static void ddp_print(const u_char *, int, int, u_short, u_char, u_char);
  90. static const char *ddpskt_string(int);
  91.  
  92. /*
  93.  * Print AppleTalk Datagram Delivery Protocol packets.
  94.  */
  95. void
  96. atalk_print(register const u_char *bp, int length)
  97. {
  98.     register const struct LAP *lp;
  99.     register const struct atDDP *dp;
  100.     register const struct atShortDDP *sdp;
  101.     u_short snet;
  102.  
  103.     lp = (struct LAP *)bp;
  104.     bp += sizeof(*lp);
  105.     length -= sizeof(*lp);
  106.     switch (lp->type) {
  107.  
  108.     case lapShortDDP:
  109.         if (length < ddpSSize) {
  110.             (void)printf(" [|sddp %d]", length);
  111.             return;
  112.         }
  113.         sdp = (const struct atShortDDP *)bp;
  114.         printf("%s.%s",
  115.             ataddr_string(0, lp->src), ddpskt_string(sdp->srcSkt));
  116.         printf(" > %s.%s:",
  117.             ataddr_string(0, lp->dst), ddpskt_string(sdp->dstSkt));
  118.         bp += ddpSSize;
  119.         length -= ddpSSize;
  120.         ddp_print(bp, length, sdp->type, 0, lp->src, sdp->srcSkt);
  121.         break;
  122.  
  123.     case lapDDP:
  124.         if (length < ddpSize) {
  125.             (void)printf(" [|ddp %d]", length);
  126.             return;
  127.         }
  128.         dp = (const struct atDDP *)bp;
  129.         snet = EXTRACT_SHORT(&dp->srcNet);
  130.         printf("%s.%s", ataddr_string(snet, dp->srcNode),
  131.             ddpskt_string(dp->srcSkt));
  132.         printf(" > %s.%s:",
  133.             ataddr_string(EXTRACT_SHORT(&dp->dstNet), dp->dstNode),
  134.             ddpskt_string(dp->dstSkt));
  135.         bp += ddpSize;
  136.         length -= ddpSize;
  137.         ddp_print(bp, length, dp->type, snet, dp->srcNode, dp->srcSkt);
  138.         break;
  139.  
  140. #ifdef notdef
  141.     case lapKLAP:
  142.         klap_print(bp, length);
  143.         break;
  144. #endif
  145.  
  146.     default:
  147.         printf("%d > %d at-lap#%d %d",
  148.             lp->src, lp->dst, lp->type, length);
  149.         break;
  150.     }
  151. }
  152.  
  153. /* XXX should probably pass in the snap header and do checks like arp_print() */
  154. void
  155. aarp_print(register const u_char *bp, int length)
  156. {
  157.     register const struct aarp *ap;
  158.  
  159. #define AT(member) ataddr_string((ap->member[1]<<8)|ap->member[2],ap->member[3])
  160.  
  161.     printf("aarp ");
  162.     ap = (const struct aarp *)bp;
  163.     if (ap->htype == 1 && ap->ptype == ETHERTYPE_ATALK &&
  164.         ap->halen == 6 && ap->palen == 4 )
  165.         switch (ap->op) {
  166.  
  167.         case 1:                /* request */
  168.             (void)printf("who-has %s tell %s",
  169.                 AT(pdaddr), AT(psaddr));
  170.             return;
  171.  
  172.         case 2:                /* response */
  173.             (void)printf("reply %s is-at %s",
  174.                 AT(pdaddr), etheraddr_string(ap->hdaddr));
  175.             return;
  176.  
  177.         case 3:                /* probe (oy!) */
  178.             (void)printf("probe %s tell %s",
  179.                 AT(pdaddr), AT(psaddr));
  180.             return;
  181.         }
  182.     (void)printf("len %d op %d htype %d ptype %#x halen %d palen %d",
  183.         length, ap->op, ap->htype, ap->ptype, ap->halen, ap->palen );
  184. }
  185.  
  186. static void
  187. ddp_print(register const u_char *bp, register int length, register int t,
  188.       register u_short snet, register u_char snode, u_char skt)
  189. {
  190.  
  191.     switch (t) {
  192.  
  193.     case ddpNBP:
  194.         nbp_print((const struct atNBP *)bp, length, snet, snode, skt);
  195.         break;
  196.  
  197.     case ddpATP:
  198.         atp_print((const struct atATP *)bp, length);
  199.         break;
  200.  
  201.     default:
  202.         (void)printf(" at-%s %d", tok2str(type2str, NULL, t), length);
  203.         break;
  204.     }
  205. }
  206.  
  207. static void
  208. atp_print(register const struct atATP *ap, int length)
  209. {
  210.     char c;
  211.     u_int32 data;
  212.  
  213.     if ((const u_char *)(ap + 1) > snapend) {
  214.         /* Just bail if we don't have the whole chunk. */
  215.         fputs(tstr, stdout);
  216.         return;
  217.     }
  218.     length -= sizeof(*ap);
  219.     switch (ap->control & 0xc0) {
  220.  
  221.     case atpReqCode:
  222.         (void)printf(" atp-req%s %d",
  223.                  ap->control & atpXO? " " : "*",
  224.                  EXTRACT_SHORT(&ap->transID));
  225.  
  226.         atp_bitmap_print(ap->bitmap);
  227.  
  228.         if (length != 0)
  229.             (void)printf(" [len=%d]", length);
  230.  
  231.         switch (ap->control & (atpEOM|atpSTS)) {
  232.         case atpEOM:
  233.             (void)printf(" [EOM]");
  234.             break;
  235.         case atpSTS:
  236.             (void)printf(" [STS]");
  237.             break;
  238.         case atpEOM|atpSTS:
  239.             (void)printf(" [EOM,STS]");
  240.             break;
  241.         }
  242.         break;
  243.  
  244.     case atpRspCode:
  245.         (void)printf(" atp-resp%s%d:%d (%d)",
  246.                  ap->control & atpEOM? "*" : " ",
  247.                  EXTRACT_SHORT(&ap->transID), ap->bitmap, length);
  248.         switch (ap->control & (atpXO|atpSTS)) {
  249.         case atpXO:
  250.             (void)printf(" [XO]");
  251.             break;
  252.         case atpSTS:
  253.             (void)printf(" [STS]");
  254.             break;
  255.         case atpXO|atpSTS:
  256.             (void)printf(" [XO,STS]");
  257.             break;
  258.         }
  259.         break;
  260.  
  261.     case atpRelCode:
  262.         (void)printf(" atp-rel  %d", EXTRACT_SHORT(&ap->transID));
  263.  
  264.         atp_bitmap_print(ap->bitmap);
  265.  
  266.         /* length should be zero */
  267.         if (length)
  268.             (void)printf(" [len=%d]", length);
  269.  
  270.         /* there shouldn't be any control flags */
  271.         if (ap->control & (atpXO|atpEOM|atpSTS)) {
  272.             c = '[';
  273.             if (ap->control & atpXO) {
  274.                 (void)printf("%cXO", c);
  275.                 c = ',';
  276.             }
  277.             if (ap->control & atpEOM) {
  278.                 (void)printf("%cEOM", c);
  279.                 c = ',';
  280.             }
  281.             if (ap->control & atpSTS) {
  282.                 (void)printf("%cSTS", c);
  283.                 c = ',';
  284.             }
  285.             (void)printf("]");
  286.         }
  287.         break;
  288.  
  289.     default:
  290.         (void)printf(" atp-0x%x  %d (%d)", ap->control,
  291.                  EXTRACT_SHORT(&ap->transID), length);
  292.         break;
  293.     }
  294.     data = EXTRACT_LONG(&ap->userData);
  295.     if (data != 0)
  296.         (void)printf(" 0x%x", data);
  297. }
  298.  
  299. static void
  300. atp_bitmap_print(register u_char bm)
  301. {
  302.     register char c;
  303.     register int i;
  304.  
  305.     /*
  306.      * The '& 0xff' below is needed for compilers that want to sign
  307.      * extend a u_char, which is the case with the Ultrix compiler.
  308.      * (gcc is smart enough to eliminate it, at least on the Sparc).
  309.      */
  310.     if ((bm + 1) & (bm & 0xff)) {
  311.         c = '<';
  312.         for (i = 0; bm; ++i) {
  313.             if (bm & 1) {
  314.                 (void)printf("%c%d", c, i);
  315.                 c = ',';
  316.             }
  317.             bm >>= 1;
  318.         }
  319.         (void)printf(">");
  320.     } else {
  321.         for (i = 0; bm; ++i)
  322.             bm >>= 1;
  323.         if (i > 1)
  324.             (void)printf("<0-%d>", i - 1);
  325.         else
  326.             (void)printf("<0>");
  327.     }
  328. }
  329.  
  330. static void
  331. nbp_print(register const struct atNBP *np, int length, register u_short snet,
  332.       register u_char snode, register u_char skt)
  333. {
  334.     register const struct atNBPtuple *tp =
  335.             (struct atNBPtuple *)((u_char *)np + nbpHeaderSize);
  336.     int i = length;
  337.     const u_char *ep;
  338.  
  339.     length -= nbpHeaderSize;
  340.     if (length < 8) {
  341.         /* must be room for at least one tuple */
  342.         (void)printf(" truncated-nbp %d", length + nbpHeaderSize);
  343.         return;
  344.     }
  345.     /* ep points to end of available data */
  346.     ep = snapend;
  347.     if ((const u_char *)tp > ep) {
  348.         fputs(tstr, stdout);
  349.         return;
  350.     }
  351.     switch (i = np->control & 0xf0) {
  352.  
  353.     case nbpBrRq:
  354.     case nbpLkUp:
  355.         (void)printf(i == nbpLkUp? " nbp-lkup %d:":" nbp-brRq %d:",
  356.                  np->id);
  357.         if ((const u_char *)(tp + 1) > ep) {
  358.             fputs(tstr, stdout);
  359.             return;
  360.         }
  361.         (void)nbp_name_print(tp, ep);
  362.         /*
  363.          * look for anomalies: the spec says there can only
  364.          * be one tuple, the address must match the source
  365.          * address and the enumerator should be zero.
  366.          */
  367.         if ((np->control & 0xf) != 1)
  368.             (void)printf(" [ntup=%d]", np->control & 0xf);
  369.         if (tp->enumerator)
  370.             (void)printf(" [enum=%d]", tp->enumerator);
  371.         if (EXTRACT_SHORT(&tp->net) != snet ||
  372.             tp->node != snode || tp->skt != skt)
  373.             (void)printf(" [addr=%s.%d]",
  374.                 ataddr_string(EXTRACT_SHORT(&tp->net),
  375.                 tp->node), tp->skt);
  376.         break;
  377.  
  378.     case nbpLkUpReply:
  379.         (void)printf(" nbp-reply %d:", np->id);
  380.  
  381.         /* print each of the tuples in the reply */
  382.         for (i = np->control & 0xf; --i >= 0 && tp; )
  383.             tp = nbp_tuple_print(tp, ep, snet, snode, skt);
  384.         break;
  385.  
  386.     default:
  387.         (void)printf(" nbp-0x%x  %d (%d)", np->control, np->id,
  388.                 length);
  389.         break;
  390.     }
  391. }
  392.  
  393. /* print a counted string */
  394. static const char *
  395. print_cstring(register const char *cp, register const u_char *ep)
  396. {
  397.     register int length;
  398.  
  399.     if (cp >= (const char *)ep) {
  400.         fputs(tstr, stdout);
  401.         return (0);
  402.     }
  403.     length = *cp++;
  404.  
  405.     /* Spec says string can be at most 32 bytes long */
  406.     if (length < 0 || length > 32) {
  407.         (void)printf("[len=%d]", length);
  408.         return (0);
  409.     }
  410.     while (--length >= 0) {
  411.         if (cp >= (char *)ep) {
  412.             fputs(tstr, stdout);
  413.             return (0);
  414.         }
  415.         putchar(*cp++);
  416.     }
  417.     return (cp);
  418. }
  419.  
  420. static const struct atNBPtuple *
  421. nbp_tuple_print(register const struct atNBPtuple *tp,
  422.         register const u_char *ep,
  423.         register u_short snet, register u_char snode,
  424.         register u_char skt)
  425. {
  426.     register const struct atNBPtuple *tpn;
  427.  
  428.     if ((const u_char *)(tp + 1) > ep) {
  429.         fputs(tstr, stdout);
  430.         return 0;
  431.     }
  432.     tpn = nbp_name_print(tp, ep);
  433.  
  434.     /* if the enumerator isn't 1, print it */
  435.     if (tp->enumerator != 1)
  436.         (void)printf("(%d)", tp->enumerator);
  437.  
  438.     /* if the socket doesn't match the src socket, print it */
  439.     if (tp->skt != skt)
  440.         (void)printf(" %d", tp->skt);
  441.  
  442.     /* if the address doesn't match the src address, it's an anomaly */
  443.     if (EXTRACT_SHORT(&tp->net) != snet || tp->node != snode)
  444.         (void)printf(" [addr=%s]",
  445.             ataddr_string(EXTRACT_SHORT(&tp->net), tp->node));
  446.  
  447.     return (tpn);
  448. }
  449.  
  450. static const struct atNBPtuple *
  451. nbp_name_print(const struct atNBPtuple *tp, register const u_char *ep)
  452. {
  453.     register const char *cp = (const char *)tp + nbpTupleSize;
  454.  
  455.     putchar(' ');
  456.  
  457.     /* Object */
  458.     putchar('"');
  459.     if ((cp = print_cstring(cp, ep)) != NULL) {
  460.         /* Type */
  461.         putchar(':');
  462.         if ((cp = print_cstring(cp, ep)) != NULL) {
  463.             /* Zone */
  464.             putchar('@');
  465.             if ((cp = print_cstring(cp, ep)) != NULL)
  466.                 putchar('"');
  467.         }
  468.     }
  469.     return ((const struct atNBPtuple *)cp);
  470. }
  471.  
  472.  
  473. #define HASHNAMESIZE 4096
  474.  
  475. struct hnamemem {
  476.     int addr;
  477.     char *name;
  478.     struct hnamemem *nxt;
  479. };
  480.  
  481. static struct hnamemem hnametable[HASHNAMESIZE];
  482.  
  483. static const char *
  484. ataddr_string(u_short atnet, u_char athost)
  485. {
  486.     register struct hnamemem *tp, *tp2;
  487.     register int i = (atnet << 8) | athost;
  488.     char nambuf[256];
  489.     static int first = 1;
  490.     FILE *fp;
  491.  
  492.     /*
  493.      * if this is the first call, see if there's an AppleTalk
  494.      * number to name map file.
  495.      */
  496.     if (first && (first = 0, !nflag)
  497.         && (fp = fopen("/etc/atalk.names", "r"))) {
  498.         char line[256];
  499.         int i1, i2, i3;
  500.  
  501.         while (fgets(line, sizeof(line), fp)) {
  502.             if (line[0] == '\n' || line[0] == 0 || line[0] == '#')
  503.                 continue;
  504.             if (sscanf(line, "%d.%d.%d %s", &i1, &i2, &i3,
  505.                      nambuf) == 4)
  506.                 /* got a hostname. */
  507.                 i3 |= ((i1 << 8) | i2) << 8;
  508.             else if (sscanf(line, "%d.%d %s", &i1, &i2,
  509.                     nambuf) == 3)
  510.                 /* got a net name */
  511.                 i3 = (((i1 << 8) | i2) << 8) | 255;
  512.             else
  513.                 continue;
  514.  
  515.             for (tp = &hnametable[i3 & (HASHNAMESIZE-1)];
  516.                  tp->nxt; tp = tp->nxt)
  517.                 ;
  518.             tp->addr = i3;
  519.             tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
  520.             tp->name = savestr(nambuf);
  521.         }
  522.         fclose(fp);
  523.     }
  524.  
  525.     for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
  526.         if (tp->addr == i)
  527.             return (tp->name);
  528.  
  529.     /* didn't have the node name -- see if we've got the net name */
  530.     i |= 255;
  531.     for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt)
  532.         if (tp2->addr == i) {
  533.             tp->addr = (atnet << 8) | athost;
  534.             tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
  535.             (void)sprintf(nambuf, "%s.%d", tp2->name, athost);
  536.             tp->name = savestr(nambuf);
  537.             return (tp->name);
  538.         }
  539.  
  540.     tp->addr = (atnet << 8) | athost;
  541.     tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
  542.     if (athost != 255)
  543.         (void)sprintf(nambuf, "%d.%d.%d",
  544.             atnet >> 8, atnet & 0xff, athost);
  545.     else
  546.         (void)sprintf(nambuf, "%d.%d", atnet >> 8, atnet & 0xff);
  547.     i = strlen(nambuf) + 1;
  548.     tp->name = strcpy(malloc((u_int) i), nambuf);
  549.  
  550.     return (tp->name);
  551. }
  552.  
  553. static struct token skt2str[] = {
  554.     { rtmpSkt,    "rtmp" },    /* routing table maintenance */
  555.     { nbpSkt,    "nis" },    /* name info socket */
  556.     { echoSkt,    "echo" },    /* AppleTalk echo protocol */
  557.     { zipSkt,    "zip" },    /* zone info protocol */
  558.     { 0,        NULL }
  559. };
  560.  
  561. static const char *
  562. ddpskt_string(register int skt)
  563. {
  564.     static char buf[8];
  565.  
  566.     if (nflag) {
  567.         (void)sprintf(buf, "%d", skt);
  568.         return (buf);
  569.     }
  570.     return (tok2str(skt2str, "%d", skt));
  571. }
  572.